#!/usr/bin/env python
#

"""Utility to send email via a third-party smtp server
"""

__version__ = "$Revision$"
# Last Modified on $Date$
# by $Author$
# from $Source$

from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
import sys
import smtplib

import mutils
from mutils import log

def send_email(server, user_name, passwd, send_from, send_to, subject, text, attach_files=[], verbose=0):
    """
    Logs in to smtp server using user_name/passwd and sends email.
    """

    if not mutils.online():
        log.error('Internet connection not available. Email can not be sent.')
        return 1

    #server, user_name, passwd
    if not server or not user_name or not passwd or not send_to:
        raise ValueError('server, user_name, passwd and send_to can not be empty')

    assert type(send_to) == list
    assert type(attach_files) == list

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    for f in attach_files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(f,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
        msg.attach(part)

    try:
        smtp = smtplib.SMTP(server)
    except:
        log.critical("Unable to connect to %s" % server)
        raise

    smtp.set_debuglevel(verbose)

    #gmail needs SSL connection
    if server.count('gmail'):
        smtp.ehlo(user_name)
        smtp.starttls()
        smtp.ehlo(user_name)


    try:
        smtp.login(user_name, passwd)
    except SMTPAuthenticationError:
        log.critical("Invalid Username or Password")
        raise

    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()


def process_cmd_line():
    """
    Reads the command-line options and invokes send_email()

    Example 1:
      smtp_server = "smtp.mail.yahoo.co.in:587"
      smtp_user = "abcd"
      smtp_pass = "abcd_password"
      from_addr = "abcd@yahoo.co.in"
      to_addr = ["xyz@gmail.com"]
      subject = "Test Sub"
      msg = "test message"
      files = ["~/Desktop/file.txt", "/tmp/abcd.zip"]

    Example 2:
      smtp_server = "smtp.gmail.com"
      smtp_user = "abcd@gmail.com"
      smtp_pass = "abcd_password"
      from_addr = "abcd@gmail.com"
      to_addr = ["xyz@gmail.com"]
      subject = "Test Sub"
      msg = "test message"
      files = ["~/Desktop/file.txt", "/tmp/abcd.zip"]

    send_email(smtp_server, smtp_user, smtp_pass, from_addr, to_addr, subject, msg, files)
    """

    import sys
    from optparse import OptionParser

    parser = OptionParser(version = __version__)
    parser.add_option("-r", "--smtp-server",
                        dest = "smtp_server")
    parser.add_option("-u", "--smtp-user",
                        dest = "smtp_user")
    parser.add_option("-i", "--smtp-pass",
                        dest = "smtp_pass")
    parser.add_option("-f", "--from-addr",
                        dest = "from_addr")
    parser.add_option("-t", "--to-addr",
                        dest = "to_addr",
                        action ="append",
                        default = [])
    parser.add_option("-s", "--subject",
                        dest = "subject")
    parser.add_option("-a", "--attach",
                        dest = "files",
                        action ="append",
                        default = [])
    parser.add_option("-m", "--message",
                        dest = "body")
    parser.add_option("-V", "--verbose",
                        action = "store_true",
                        dest = "verbose")


    (options, args) = parser.parse_args()

    if not options.smtp_server:
        parser.error('SMTP server is missing.')
    elif not options.smtp_user:
        parser.error('SMTP userId is missing.')
    elif not options.smtp_pass:
        parser.error('SMTP password is missing.')
    elif not options.to_addr:
        parser.error('To address is missing.')

    log.debug(options)

    send_email(options.smtp_server,
               options.smtp_user,
               options.smtp_pass,
               options.from_addr,
               options.to_addr,
               options.subject,
               options.body,
               options.files,
               options.verbose)


#The following code will be executed only if called as stand-alone script.
#Skipped if imported as module
if __name__ == "__main__":
    sys.exit(process_cmd_line())
